﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Clandestine;
using Tao.Platform.Windows;
using System.Threading;
using System.IO;
using Tao.OpenGl;
using System.Drawing;
using Clandestine.Entities;
using Slick.MapEditor.Tools;
using Slick.MapEditor;

namespace Slick
{
    public static class Program
    {

        public static bool Running = true;

        public static frmSlick fSlick;

        public static Sprite Grid;
        public static bool ShowGrid
        {
            get 
            {
                if (Grid != null)
                    return Grid.Visible;
                else
                    return false;
            }
            set 
            {
                if (Grid != null)
                    Grid.Visible = value;
                else
                    throw new Exception();
            }
        }
        public static float gridTransparency = 0.5f;
        public static float GridTransparency
        {
            get { return gridTransparency; }
            set { gridTransparency = value; RedrawGrid(); }
        }
        public static int drawnGridSize = 16;
        public static int DrawnGridSize
        {
            get { return drawnGridSize; }
            set { drawnGridSize = value; RedrawGrid(); }
        }

        // Actual grid size. the above is just for well.. the drawn one.
        public static int GridSize = 16;

        public static void RedrawGrid()
        {
            Bitmap bmp = new Bitmap(Clandestine.Graphics.ScreenWidth + (DrawnGridSize * 2), Clandestine.Graphics.ScreenHeight + (DrawnGridSize * 2)); // Probably don't need the *2
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
            Pen p = new Pen(Color.FromArgb((int)(GridTransparency*255), 0, 0, 0), 1);

            // Vertical
            for (int x = DrawnGridSize - 1; x < bmp.Width; x += DrawnGridSize)
                g.DrawLine(p, x, 0, x, bmp.Height);
 
            // Horiz
            for (int y = DrawnGridSize - 1; y < bmp.Height; y += DrawnGridSize)
                g.DrawLine(p, 0, y, bmp.Width, y);

            g.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);
            g.Dispose(); // I doubt I need to do this. GC and all that
            p.Dispose();
            // Made the sprite?
            if (Grid == null)
            {
                Grid = new Sprite();
                Grid.Visible = false;
            }
            Grid.SetTexture(new Texture("{GRID}!" + DrawnGridSize, bmp));
        }

        public static void ReloadTilesets()
        {
            Tilesets.LoadedTilesets.Clear();

            //Tilesets.LoadTileset("Special Tiles");
            //lock (Tilesets.LoadedTilesets)
            //Tilesets.LoadedTilesets.Add("Special Tiles");
            foreach (string filename in Directory.GetFiles(Directory.GetCurrentDirectory(), "*tile*.png", SearchOption.AllDirectories))
                if (filename.Substring(Directory.GetCurrentDirectory().Length + 1) != "specialtiles.png")
                    Tilesets.LoadTileset(filename.Substring(Directory.GetCurrentDirectory().Length + 1));
        }

        public static void ResetLevel()
        {
            lock (Tilesets.LoadedTilesets)
                Tilesets.LoadedTilesets.Clear();
            
            // *shrugs* can't find another way to access the Map!
            ((MapMode)Editor.CurrentMode).Map.Layers.Clear();
            ((MapMode)Editor.CurrentMode).Map.Entities.Clear();
            
            Camera.Position = PointF.Empty;
            Camera.Zoom = 1f;
            Camera.Angle = 0f;
           // ToolController.Deinitialise();
            Texture.ForceDestroyAllTextures();
            //ToolController.Initialise();
          //  foreach (Entity ent in Entities.AllEntities)
           //     ent.Dispose();
            
            //Entities.AllEntities.Clear();
        }

        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Sort out working directory
            Directory.SetCurrentDirectory("../datas/");
            Clandestine.Program.WorkingDirectoryFixUp();

            // Initialise stuff -- graphics initialisation done in main thread.
            Fonts.Initialise(); // even needed?
            //ToolController.Initialise();
            ReloadTilesets();

            // Setup the main form.
            fSlick = new frmSlick();
            fSlick.WindowState = FormWindowState.Maximized;
            fSlick.Show();

            // Remember, this takes over the thread.
            // No code after this will execute 'til the main form is closed!
            Application.Run(fSlick);

            //ToolController.Deinitialise();
        }


        private static void clandestineRenderThread(object manager)
        {


            Clandestine.Graphics.Initialise(1, (IGlManager) manager);
            

            // takes too long, we push way more quads than the real game will!
            Clandestine.Graphics.PerformSlowDebugDepthChecking = false;

            Clandestine.Graphics.SetWindowTitle("GRAB IT!");

            while (Running && Clandestine.Program.Running)
            {
                // If they try to close the window, reset the operation.
                if (!Clandestine.Program.Running)
                    Clandestine.Program.Running = true;

                // Keyboard panning! wasd keys
                // This is very naughty... should use Keyboard stuffs/Add to Keyboard.cs
               /* int vel = 5;
                if (Glfw.glfwGetKey('W') > 0)
                    Camera.Position.Y -= vel;
                if (Glfw.glfwGetKey('S') > 0)
                    Camera.Position.Y += vel;
                if (Glfw.glfwGetKey('A') > 0)
                    Camera.Position.X -= vel;
                if (Glfw.glfwGetKey('D') > 0)
                    Camera.Position.X += vel;*/

                // Lets do some grid!
                if (ShowGrid)
                {
                    // Make sure position is right
                    Grid.Position = Point.Round(Camera.Position);
                    Grid.X -= ((int)Camera.Position.X) % GridSize;
                    Grid.Y -= ((int)Camera.Position.Y) % GridSize;
                    Grid.Layer = float.MaxValue; // shouldn't be HERE. nvm.
                }

                Gl.glMatrixMode(Gl.GL_PROJECTION);
                Gl.glLoadIdentity();
                //Glu.gluOrtho2D(0, ScreenWidth, ScreenHeight, 0);
                int w, h;
                Clandestine.Graphics.Manager.GetViewportSize(out w, out h);
                Gl.glOrtho(0, w, h, 0, -1000, 1000);

                Clandestine.Graphics.Render();
            }

            Keyboard.Deinitialise();
            Clandestine.Graphics.Deinitialise();
        }
    }
}
